#pragma once
#define BATTLEFIRE_DEPRECATED __declspec(deprecated)
#if defined(__GNUC__)
#define ALIGN_OF(T) __alignof__(T)
#define ALIGN_TYPE(val) __attribute__((aligned(val)))
#define FORCE_INLINE inline __attribute__ ((always_inline))
#elif defined(_MSC_VER)
#define ALIGN_OF(T) __alignof(T)
#define ALIGN_TYPE(val) __declspec(align(val))
#define FORCE_INLINE __forceinline
#else
#define BattleFire_TYPE(size)
#define FORCE_INLINE inline
#endif
//types
#if BATTLEFIRE_IPHONE_PLAYER || BATTLEFIRE_ANDROID_PLAYER
#define _MAX_PATH 256
#endif

#if BATTLEFIRE_EDITOR || BATTLEFIRE_WIN_PLAYER
#define BATTLEFIRE_PLATFORM_WIN 1
#define BATTLEFIRE_APICALL __stdcall
#define NOMINMAX
#include <WinSock2.h>
#include <windows.h>
#include <WinNls.h>
#include <wchar.h>
#include <tchar.h>
#include <io.h>
#elif defined(BATTLEFIRE_OSX_PLAYER) || defined(BATTLEFIRE_ANDROID_PLAYER) || defined(BATTLEFIRE_IPHONE_PLAYER)
#define BATTLEFIRE_PLATFORM_UNIX 1
#define BATTLEFIRE_APICALL
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h>
#include <net/if.h>
#include <pthread.h>
#include <dirent.h>
#ifdef BATTLEFIRE_IPHONE_PLAYER
#include <ifaddrs.h>
#define BATTLEFIRE_MOBILE_PLAYER 1
#endif
#ifdef BATTLEFIRE_ANDROID_PLAYER
#define BATTLEFIRE_MOBILE_PLAYER 1
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <android/native_window_jni.h>
#include <dirent.h>
#define JAVA_API(return_type) extern "C" JNIEXPORT return_type JNICALL
#define JFOO(CLS,METHOD) Java_cn_battlefire_androidplayer_##CLS##_##METHOD
#if defined(__arm64__)||defined(__aarch64__)
#define ANDROID_ARCH "arm64-v8a"
#elif defined(__arm__)
#define ANDROID_ARCH "armeabi-v7a"
#else
#define ANDROID_ARCH "Unkown"
#endif
#endif
#endif
#include <string>
#include <string.h>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <thread>
#include <mutex>
#include <algorithm>
#include <stdint.h>
#include <condition_variable>
typedef signed char BattleFireSInt8;
typedef unsigned char BattleFireUInt8;
typedef BattleFireUInt8 BattleFireUByte;
typedef BattleFireSInt8 BattleFireByte;
typedef signed short BattleFireSInt16;
typedef unsigned short BattleFireUInt16;
typedef int BattleFireSInt32;
typedef unsigned int BattleFireUInt32;
typedef unsigned long long BattleFireUInt64;
typedef signed long long BattleFireSInt64;
typedef BattleFireSInt32 LuaScriptHandle;
typedef void* BattleFireAny;
#ifndef _MAX_PATH
#define _MAX_PATH 260
#endif

#define PLATFORM_CACHE_LINE_SIZE 64

#if defined(__GNUC__)
#define ALIGN_OF(T) __alignof__(T)
#define ALIGN_TYPE(val) __attribute__((aligned(val)))
#define FORCE_INLINE inline __attribute__ ((always_inline))
#elif defined(_MSC_VER)
#define ALIGN_OF(T) __alignof(T)
#define ALIGN_TYPE(val) __declspec(align(val))
#define FORCE_INLINE __forceinline
#define MS_ALIGN(n)
#define GCC_ALIGN(n)
#define INDEX_NONE -1
#else
#define ALIGN_TYPE(size)
#define FORCE_INLINE inline
#endif
class FNoncopyable {
protected:
	FNoncopyable() {}
	~FNoncopyable() {}
private:
	FNoncopyable(const FNoncopyable&);
	FNoncopyable& operator=(const FNoncopyable&);
};


template<typename T32BITS, typename T64BITS, int PointerSize>
struct SelectIntPointerType {};
template<typename T32BITS, typename T64BITS>
struct SelectIntPointerType<T32BITS, T64BITS, 8> {
	typedef T64BITS TIntPointer;
};
template<typename T32BITS, typename T64BITS>
struct SelectIntPointerType<T32BITS, T64BITS, 4> {
	typedef T32BITS TIntPointer;
};
struct FGenericPlatformTypes
{
	typedef unsigned char 		uint8;
	typedef unsigned short int	uint16;
	typedef unsigned int		uint32;
	typedef unsigned long long	uint64;
	typedef	signed char			int8;
	typedef signed short int	int16;
	typedef signed int	 		int32;
	typedef signed long long	int64;
	typedef char				ANSICHAR;
	typedef wchar_t				WIDECHAR;
	typedef uint8				CHAR8;
	typedef uint16				CHAR16;
	typedef uint32				CHAR32;
	typedef WIDECHAR			TCHAR;
	typedef SelectIntPointerType<uint32, uint64, sizeof(void*)>::TIntPointer UPTRINT;
	typedef SelectIntPointerType<int32, int64, sizeof(void*)>::TIntPointer PTRINT;
	typedef UPTRINT SIZE_T;
	typedef PTRINT SSIZE_T;
	typedef int32					TYPE_OF_NULL;
	typedef decltype(nullptr)		TYPE_OF_NULLPTR;
};
struct FWindowsPlatformTypes : public FGenericPlatformTypes
{
#ifdef _WIN64
	typedef unsigned __int64	SIZE_T;
	typedef __int64				SSIZE_T;
#else
	typedef unsigned long		SIZE_T;
	typedef long				SSIZE_T;
#endif
};
typedef FWindowsPlatformTypes FPlatformTypes;

typedef FPlatformTypes::uint8		uint8;
typedef FPlatformTypes::uint16		uint16;
typedef FPlatformTypes::uint32		uint32;
typedef FPlatformTypes::uint64		uint64;
typedef	FPlatformTypes::int8		int8;
typedef FPlatformTypes::int16		int16;
typedef FPlatformTypes::int32		int32;
typedef FPlatformTypes::int64		int64;
typedef FPlatformTypes::ANSICHAR	ANSICHAR;
typedef FPlatformTypes::WIDECHAR	WIDECHAR;
typedef FPlatformTypes::TCHAR		TCHAR;
typedef FPlatformTypes::CHAR8		UTF8CHAR;
typedef FPlatformTypes::CHAR16		UCS2CHAR;
typedef FPlatformTypes::CHAR16		UTF16CHAR;
typedef FPlatformTypes::CHAR32		UTF32CHAR;
typedef FPlatformTypes::UPTRINT UPTRINT;
typedef FPlatformTypes::PTRINT PTRINT;
typedef FPlatformTypes::SIZE_T SIZE_T;
typedef FPlatformTypes::SSIZE_T SSIZE_T;
typedef FPlatformTypes::TYPE_OF_NULL	TYPE_OF_NULL;
typedef FPlatformTypes::TYPE_OF_NULLPTR	TYPE_OF_NULLPTR;

#define MIN_uint8		((uint8)	0x00)
#define	MIN_uint16		((uint16)	0x0000)
#define	MIN_uint32		((uint32)	0x00000000)
#define MIN_uint64		((uint64)	0x0000000000000000)
#define MIN_int8		((int8)		-128)
#define MIN_int16		((int16)	-32768)
#define MIN_int32		((int32)	0x80000000)
#define MIN_int64		((int64)	0x8000000000000000)

#define MAX_uint8		((uint8)	0xff)
#define MAX_uint16		((uint16)	0xffff)
#define MAX_uint32		((uint32)	0xffffffff)
#define MAX_uint64		((uint64)	0xffffffffffffffff)
#define MAX_int8		((int8)		0x7f)
#define MAX_int16		((int16)	0x7fff)
#define MAX_int32		((int32)	0x7fffffff)
#define MAX_int64		((int64)	0x7fffffffffffffff)

#define MIN_flt			(1.175494351e-38F)			/* min positive value */
#define MAX_flt			(3.402823466e+38F)
#define MIN_dbl			(2.2250738585072014e-308)	/* min positive value */
#define MAX_dbl			(1.7976931348623158e+308)

#if BATTLEFIRE_PLATFORM_WIN
#define BattleFireSocket SOCKET
#define BattleFireFDSet fd_set
#define BattleFireAddressInfo addrinfo
#define NewSocket socket
#define BattleFireCloseSocket closesocket
#define BattleFire_STRICMP _stricmp
#define BattleFireSleep(ms) Sleep(ms)
#else
#include <sys/time.h>
#define NewSocket socket
#define BattleFireFDSet fd_set
#define BattleFireAddressInfo addrinfo
#define BattleFireSocket int
#define BattleFireCloseSocket close
#define BattleFireSleep(ms) CanRead(0,0,ms)
#define BattleFire_STRICMP strcasecmp
#endif

#define BATTLEFIRE_PTRDIFF_TO_INT32(argument) static_cast<int32>(argument)
#define BATTLEFIRE_PTRDIFF_TO_UINT32(argument) static_cast<uint32>(argument)
#define _00000000_00000000_00000000_00000001 1
#define _00000000_00000000_00000000_00000010 2
#define _00000000_00000000_00000000_00000100 4
#define _00000000_00000000_00000000_00001000 8
#define _00000000_00000000_00000000_00010000 16
#define _00000000_00000000_00000000_00100000 32
#define _00000000_00000000_00000000_01000000 64
#define _00000000_00000000_00000000_10000000 128
#define _00000000_00000000_00000001_00000000 256
#define _00000000_00000000_00000010_00000000 512
#define _00000000_00000000_00000100_00000000 1024
#define _00000000_00000000_00001000_00000000 2048
#define _00000000_00000000_00010000_00000000 4096
#define _00000000_00000000_00100000_00000000 8192
#define _00000000_00000000_01000000_00000000 16384
#define _00000000_00000000_10000000_00000000 32768
#define _00000000_00000001_00000000_00000000 65536
#define _00000000_00000010_00000000_00000000 131072
#define _00000000_00000100_00000000_00000000 262144
#define _00000000_00001000_00000000_00000000 524288
#define _00000000_00010000_00000000_00000000 1048576
#define _00000000_00100000_00000000_00000000 2097152
#define _00000000_01000000_00000000_00000000 4194304
#define _00000000_10000000_00000000_00000000 8388608
#define _00000001_00000000_00000000_00000000 16777216
#define _00000010_00000000_00000000_00000000 33554432
#define _00000100_00000000_00000000_00000000 67108864
#define _00001000_00000000_00000000_00000000 134217728
#define _00010000_00000000_00000000_00000000 268435456
#define _00100000_00000000_00000000_00000000 536870912
#define _01000000_00000000_00000000_00000000 1073741824
#define _10000000_00000000_00000000_00000000 2147483648
typedef void(*VOID_VOID_PTR_FUNCTION)(void*);

bool CanReadFD(BattleFireSocket fd, int second, int ms);

template<BattleFireSInt32 Size, BattleFireUInt32 Alignment>
struct TAlignedBytes;

template<BattleFireSInt32 Size>
struct TAlignedBytes<Size, 1>
{
	BattleFireUInt8 Pad[Size];
};
#define IMPLEMENT_ALIGNED_STORAGE(Align) \
template<BattleFireSInt32 Size>        \
struct TAlignedBytes<Size,Align> \
{ \
	struct MS_ALIGN(Align) TPadding \
	{ \
		BattleFireUInt8 Pad[Size]; \
	} GCC_ALIGN(Align); \
	TPadding Padding; \
};
IMPLEMENT_ALIGNED_STORAGE(16);
IMPLEMENT_ALIGNED_STORAGE(8);
IMPLEMENT_ALIGNED_STORAGE(4);
IMPLEMENT_ALIGNED_STORAGE(2);
#undef IMPLEMENT_ALIGNED_STORAGE
template<typename ElementType>
struct TTypeCompatibleBytes :
	public TAlignedBytes<
	sizeof(ElementType),
	alignof(ElementType)
	>
{
	ElementType* GetTypedPtr() { return (ElementType*)this; }
	const ElementType* GetTypedPtr() const { return (const ElementType*)this; }
};